﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CRUD_Layer.Session;
using NHibernate;
using NHibernate.Criterion;

namespace CRUD_Layer.CommandObjects
{
    public abstract class GenericDAO<TEntity> where TEntity : IEntity, new()
    {
        public static TEntity Get(int Id)
        {

            using (ISession session = SessionManager.OpenSession())
            {
                try
                {
                    return session.Get<TEntity>(Id);
                }
                catch (Exception ex)
                {
                    
                }
                return session.Get<TEntity>(Id);
            }
        }

        public static TEntity Save(TEntity obj)
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        if (obj == null)
                            throw new ArgumentNullException("Object cannot be null!");
                        session.SaveOrUpdate(obj);
                        transaction.Commit();
                        session.Flush();
                        return obj;
                    }
                }
            }
            catch (Exception ex)
            {

            }
            return new TEntity();
        }

        public static void Delete(TEntity obj)
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        if (obj == null)
                            throw new ArgumentNullException("Object must not be null!");

                        session.Delete(obj);
                        session.Flush();
                        transaction.Commit();
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public static IList<TEntity> ListAll()
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    return session.CreateCriteria(typeof(TEntity)).List<TEntity>();
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public static IList<TEntity> GetObjectListFromArray(int[] IDs)
        {
            if (IDs == null)
            {
                return null;
            }
            else
            {
                return IDs.Select(id => new TEntity { Id = id }).ToList();
            }
        }


        public static int[] GetArrayFromObjectList(IList<TEntity> t)
        {
            return t.Select(e => e.Id).ToArray();
        }

        public static int GetCountByPropertyName(string propertyName, string value)
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    return session.CreateCriteria(typeof(TEntity)).Add(Expression.Eq(propertyName, value)).List().Count;
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        public static TEntity FindOne(string propertyName, object propertyValue)
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        TEntity entity = (TEntity)session.CreateCriteria(typeof(TEntity)).Add(Expression.Eq(propertyName, propertyValue)).UniqueResult();
                        return entity;
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }
        public static IList<TEntity> FindByProperty(string PropertyName, object PropertyValue)
        {
            try
            {
                using (ISession session = SessionManager.OpenSession())
                {
                    using (ITransaction transaction = session.BeginTransaction())
                    {
                        IList<TEntity> Entities = (IList<TEntity>)session.CreateCriteria(typeof(TEntity)).Add(Expression.Eq(PropertyName, PropertyValue)).List<TEntity>();
                        return Entities;
                    }
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

    }

    public interface IEntity
    {
        int Id { get; set; }
    }
}
